package model;

import Interfaces.Ficha;

public abstract class Variator {

	/**
	 * Interfaz simple que permite variar una ficha a otra utilizando 
	 * rotaciones y orientaciones.
	 * @param base ficha para trabajar
	 * @return ficha variada
	 */
	public abstract Ficha variate(Ficha base);
	
	static Variator[] DEFAULTS;

	/**
	 * Composite de Variators que permite armar variator compuestos.
	 */
	public static class Composite extends Variator {
		
		final Variator[] variators;
		
		public Composite(final Variator... variators) {
			super();
			this.variators = variators;
		}
		
		@Override
		public Ficha variate(final Ficha base) {
			Ficha fichaVariada = base;
			for (Variator variator : this.variators) {
				fichaVariada = variator.variate(fichaVariada);
			}
			return fichaVariada;
		}
		
	}

	static {
		final Variator espejoHorizontal = new Variator() {
			@Override
			public Ficha variate(Ficha base) {
				final Ficha ficha = new Ficha(base.getNombre(), 
						base.obtenerX(), base.obtenerY());
				for (int i = 0; i < base.obtenerX(); i++) {
					for (int j = 0; j < base.obtenerY(); j++) {
						ficha.setearValor(i, j, 
								base.valor(i, base.obtenerY() - j - 1));
					}
				}
				return ficha;
			}
		};
		final Variator espejoVertical = new Variator() {
			@Override
			public Ficha variate(Ficha base) {
				final Ficha ficha = new Ficha(base.getNombre(), 
						base.obtenerX(), base.obtenerY());
				for (int i = 0; i < base.obtenerY(); i++) {
					for (int j = 0; j < base.obtenerX(); j++) {
						ficha.setearValor(j,i, 
								base.valor(base.obtenerX() - j - 1, i));
					}
				}
				return ficha;
			}
		};
		final Variator copia = new Variator() {
			@Override
			public Ficha variate(Ficha base) {
				final Ficha ficha = new Ficha(base.getNombre(), 
						base.obtenerX(), base.obtenerY());
				for (int i = 0; i < base.obtenerX(); i++) {
					for (int j = 0; j < base.obtenerY(); j++) {
						ficha.setearValor(i,j, base.valor(i, j));
					}
				}
				return ficha;
			}
		};
		final Variator rotacion = new Variator() {
			@Override
			public Ficha variate(Ficha base) {
				final Ficha ficha = new Ficha(base.getNombre(), 
						base.obtenerY(), base.obtenerX());
				for (int i = 0; i < base.obtenerX(); i++) {
					for (int j = 0; j < base.obtenerY(); j++) {
						ficha.setearValor(j, base.obtenerX() - i - 1, 
								base.valor(i, j));
					}
				}
				return ficha;
			}
		};
		final Composite dobleRotacion = new Composite(rotacion, rotacion);
		final Composite tripleRotacion = new Composite(dobleRotacion, rotacion);
		final Composite rotacionEspejadaH = new Composite(rotacion, espejoHorizontal);
		final Composite rotacionEspejadaV = new Composite(rotacion, espejoVertical);
		final Composite rotacion2EspejadaH = new Composite(dobleRotacion, espejoHorizontal);
		final Composite rotacion2EspejadaV = new Composite(dobleRotacion, espejoVertical);
		final Composite rotacion3EspejadaH = new Composite(tripleRotacion, espejoHorizontal);
		final Composite rotacion3EspejadaV = new Composite(tripleRotacion, espejoVertical);
		DEFAULTS = new Variator[] {
			espejoHorizontal, espejoVertical, copia, rotacion,
			dobleRotacion, tripleRotacion, rotacionEspejadaH,
			rotacionEspejadaV, rotacion2EspejadaH, rotacion2EspejadaV,
			rotacion3EspejadaH, rotacion3EspejadaV
		};
	}
		
}
